import { Elysia } from 'elysia';
import z from 'zod';

import { ok, result } from '@/common/result';
import { metrics } from '@/plugins/opentelemetry';
import { may, MayError } from '@/utils/error';
import { prisma } from '@/utils/prisma-client';

/**
 * 数据库就绪错误
 */
class DatabaseReadyError extends MayError {
  public readonly name = 'DatabaseReadyError';
}

/**
 * API 路由配置
 */
export const apiRoutes = new Elysia()
  .decorate(() => {
    const meter = metrics.getMeter('status:check');
    const checkTimes = meter.createCounter('check', {
      description: '检查返回总计数值',
    });
    return { checkTimes };
  })
  .get(
    '/health',
    ({ checkTimes }) => {
      checkTimes.add(1);
      return ok({
        status: 'healthy',
        timestamp: new Date().toISOString(),
      });
    },
    {
      response: result(
        z
          .object({
            status: z.literal(['healthy']).describe('服务状态'),
            timestamp: z.iso.datetime().describe('服务运行时间戳'),
          })
          .describe('服务正常运行')
      ),
      detail: {
        summary: '健康检查',
        description: '健康检查接口',
        tags: ['系统监控'],
      },
    }
  )
  .get(
    '/ready',
    async ({ checkTimes }) => {
      checkTimes.add(1);

      // 检查数据库连接
      await may(() => prisma.$queryRaw`SELECT 1`, { kind: DatabaseReadyError });

      return ok({
        status: 'ready',
        timestamp: new Date().toISOString(),
      });
    },
    {
      response: result(
        z.object({
          status: z.literal('ready').describe('就绪状态'),
          timestamp: z.iso.datetime().describe('检查时间戳'),
        })
      ),
      detail: {
        summary: '就绪检查',
        description: '检查服务是否准备好接收流量',
        tags: ['系统监控'],
      },
    }
  )
  .group('/api/v1', app => app);
